﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Diagnostics;
using System.Drawing;
using System.IO.Ports;
using System.Linq;
using System.Management;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using HalconDotNet;
using static System.Net.Mime.MediaTypeNames;

namespace DimensionalMeasurement
{
    /// <summary>
    /// 直线信息
    /// </summary>
    [Serializable]
    public struct Line_INFO
    {
        public double StartY;//起点行坐标
        public double StartX;//起点列坐标
        public double EndY; //终点行坐标
        public double EndX;//终点列坐标
        public double Ny;//行向量
        public double Nx;//列向量
        public double Dist;//距离
        public double Phi;//方向
        public double MidY;//中间点行坐标
        public double MidX;//中间点列坐标
        public Line_INFO(double m_start_Row, double m_start_Col, double m_end_Row, double m_end_Col)
        {
            //r*Ny+c*Nx-Dist=0
            ///AX+BY+C=0        
            //A = Y2 - Y1
            //B = X1 - X2
            //C = X2*Y1 - X1*Y2
            this.StartY = m_start_Row;
            this.StartX = m_start_Col;
            this.EndY = m_end_Row;
            this.EndX = m_end_Col;
            this.Ny = m_start_Col - m_end_Col;
            this.Nx = m_end_Row - m_start_Row;
            this.Dist = m_start_Col * m_end_Row - m_end_Col * m_start_Row;
            Phi = HMisc.AngleLx(StartY, StartX, EndY, EndX);
            MidY = (StartY + EndY) / 2;
            MidX = (StartX + EndX) / 2;

        }
        //public HXLDCont genXLD()
        //{
        //    HXLDCont xld = new HXLDCont();
        //    HMeasureSet.GenArrowContourXld(out xld, StartY, StartX, EndY, EndX, 10, 10);
        //    return xld;
        //}
        public HTuple getTuple()
        {
            double[] line = new double[] { StartY, StartX, EndY, EndX };
            return new HTuple(line);
        }
    };
    /// <summary>
    /// 测量信息
    /// </summary>
    [Serializable]
    public struct Metrology_INFO
    {
        public double Length1, Length2, Threshold, MeasureDis, Sigma;
        public HTuple ParamName, ParamValue;
        public int PointsOrder;

        public Metrology_INFO(double _length1, double _length2, double _threshold, double _measureDis, HTuple _paraName, HTuple _paraValue, int _pointsOrder, double _Sigma)
        {
            this.Length1 = _length1;                        // 长/2
            this.Length2 = _length2;                        // 宽/2
            this.Threshold = _threshold;                    // 阈值
            this.MeasureDis = _measureDis;                  //间隔
            this.ParamName = _paraName;                     //参数名
            this.ParamValue = _paraValue;                   //参数值
            this.PointsOrder = _pointsOrder;                //点顺序 0位默认，1 顺时针，2 逆时针
            Sigma = _Sigma;
        }
    }
    /// <summary>
    /// 过渡方式结构体
    /// </summary>
    public enum Transition { 双向过渡, 黑到白, 白到黑 }
    /// <summary>
    /// 选择点结构体
    /// </summary>
    public enum Select { 所有点, 第一个点, 最后一个点 }
    /// <summary>
    /// 权限
    /// </summary>
    public enum Power { 操作员, 管理员, 超级管理员, 开发者权限 }

    /// <summary>
    /// 存图信息
    /// </summary>
    public struct SaveImageInfo
    {
        /// <summary>
        /// 存图路径
        /// </summary>
        public string path;
        /// <summary>
        /// 图像
        /// </summary>
        public HObject image;
        /// <summary>
        /// 图片格式
        /// </summary>
        public string format;
        /// <summary>
        /// 图像命名
        /// </summary>
        public string fileName;
    }


    /// <summary>
    /// 测量线类
    [Serializable]
    /// </summary>
    public class MeasureLine
    {
        [Category("区域"), Description("矩形中心的行坐标"), ReadOnly(true)]
        public double 行坐标 { get; set; }

        [Category("区域"), Description("矩形中心的列坐标"), ReadOnly(true)]
        public double 列坐标 { get; set; }

        [Category("区域"), Description("矩形的纵轴与水平的角度(弧度)"), ReadOnly(true)]
        public double 弧度 { get; set; }

        [Category("区域"), Description("矩形的半宽"), ReadOnly(true)]
        public double 半宽 { get; set; }

        [Category("区域"), Description("矩形的半高"), ReadOnly(true)]
        public double 半高 { get; set; }

        [Category("设置"), Description("测量点的间隔")]
        public int 步长 { get; set; }

        [Category("设置"), Description("高斯滤波系数")]
        public double 滤波系数 { get; set; }

        [Category("设置"), Description("黑白边缘灰度差")]
        public int 阈值 { get; set; }

        [Category("设置"), Description("从黑到白还是从白到黑边")]
        public Transition 过渡方式 { get; set; }

        [Category("设置"), Description("测量点的模式")]
        public Select 选择点 { get; set; }

        [Category("输出"), Description("测量出来线的起始行坐标"), ReadOnly(true)]
        public double 起始行坐标 { get; set; }


        [Category("输出"), Description("测量出来线的起始列坐标"), ReadOnly(true)]
        public double 起始列坐标 { get; set; }

        [Category("输出"), Description("测量出来线的末尾行坐标"), ReadOnly(true)]
        public double 末尾行坐标 { get; set; }

        [Category("输出"), Description("测量出来线的末尾列坐标"), ReadOnly(true)]
        public double 末尾列坐标 { get; set; }

        public MeasureLine(double row = 300, double column = 700, double phi = 0, double length1 = 400, double length2 = 50,
            int step = 10, double sigma = 1, int threshold = 40, Transition transition = Transition.黑到白, Select select = Select.第一个点,
            double rowBegin = -1, double colBegin = -1, double rowEnd = -1, double colEnd = -1)
        {
            行坐标 = row;
            列坐标 = column;
            弧度 = phi;
            半宽 = length1;
            半高 = length2;
            步长 = step;
            滤波系数 = sigma;
            阈值 = threshold;
            过渡方式 = transition;
            选择点 = select;
            起始行坐标 = rowBegin;
            起始列坐标 = colBegin;
            末尾行坐标 = rowEnd;
            末尾列坐标 = colEnd;
        }

    }


    /// <summary>
    /// 各项数据类
    /// </summary>
    public class Data
    {
        /// <summary>
        /// 拍照ID
        /// </summary>
        public string ProductID = "-1";

        /// <summary>
        /// 极片头宽
        /// </summary>
        public double JPHeadWidth = 0;
        /// <summary>
        /// 极片尾宽
        /// </summary>
        public double JPTailWidth = 0;
        /// <summary>
        /// 极片头长
        /// </summary>
        public double JPHeadLength = 0;
        /// <summary>
        /// 极片尾长
        /// </summary>
        public double JPTailLength = 0;
        /// <summary>
        /// 左极耳肩宽
        /// </summary>
        public double JELeftShoulder = 0;
        /// <summary>
        /// 右极耳肩宽
        /// </summary>
        public double JERightShoulder = 0;
        /// <summary>
        /// 极耳宽
        /// </summary>
        public double JEWidth = 0;
        /// <summary>
        /// 极耳高
        /// </summary>
        public double JEHeight = 0;
        /// <summary>
        /// 负极带料高||正极陶瓷高
        /// </summary>
        public double DLHeightOrCeramicsHeight = 0;

        /// <summary>
        /// 左上相机V角度
        /// </summary>
        public double LeftUpVAngle = 0;
        /// <summary>
        /// 左上相机V宽度
        /// </summary>
        public double LeftUpVWidth = 0;
        /// <summary>
        /// 左上相机V深度
        /// </summary>
        public double LeftUpVDepth = 0;
        /// <summary>
        /// 右上相机V角度
        /// </summary>
        public double RightUpVAngle = 0;
        /// <summary>
        /// 右上相机V宽度
        /// </summary>
        public double RightUpVWidth = 0;
        /// <summary>
        /// 右上相机V深度
        /// </summary>
        public double RightUpVDepth = 0;
        /// <summary>
        /// 左下相机V角度
        /// </summary>
        public double LeftDownVAngle = 0;
        /// <summary>
        /// 左下相机V宽度
        /// </summary>
        public double LeftDownVWidth = 0;
        /// <summary>
        /// 左下相机V深度
        /// </summary>
        public double LeftDownVDepth = 0;
        /// <summary>
        /// 右下相机V角度
        /// </summary>
        public double RightDownVAngle = 0;
        /// <summary>
        /// 右下相机V宽度
        /// </summary>
        public double RightDownVWidth = 0;
        /// <summary>
        /// 右下相机V深度
        /// </summary>
        public double RightDownVDepth = 0;
        /// <summary>
        /// 极片总宽
        /// </summary>
        public double JPTotalWidth = 0;
        /// <summary>
        /// 极片涂布高
        /// </summary>
        public double JPCoating = 0;
        /// <summary>
        /// 对角线
        /// </summary>
        public double Diagonal = 0;


        /// <summary>
        /// 左上缺角面积
        /// </summary>
        public double LeftUpBevelArea = 0;
        /// <summary>
        /// 右上缺角面积
        /// </summary>
        public double RightUpBevelArea = 0;
        /// <summary>
        /// 左下缺角面积
        /// </summary>
        public double LeftDownBevelArea = 0;
        /// <summary>
        /// 右下缺角面积
        /// </summary>
        public double RightDownBevelArea = 0;


        /// <summary>
        /// 左上相机角度
        /// </summary>
        public double LeftUpAngle = 0;
        /// <summary>
        /// 右上相机角度
        /// </summary>
        public double RightUpAngle = 0;
        /// <summary>
        /// 左下相机角度
        /// </summary>
        public double LeftDownAngle = 0;
        /// <summary>
        /// 右下相机角度
        /// </summary>
        public double RightDownAngle = 0;

        /// <summary>
        /// X偏移皮带方向
        /// </summary>
        public double X = 0;
        /// <summary>
        /// Y偏移非皮带方向
        /// </summary>
        public double Y = 0;
        /// <summary>
        /// Z偏移(角度)
        /// </summary>
        public double Z = 0;


        /// <summary>
        /// 左上markX 
        /// </summary>
        public double LeftUpMarkX = 0;
        /// <summary>
        /// 左上markY
        /// </summary>
        public double LeftUpMarkY = 0;

        /// <summary>
        /// 右上markX 
        /// </summary>
        public double RightUpMarkX = 0;
        /// <summary>
        /// 右上markY
        /// </summary>
        public double RightUpMarkY = 0;

        /// <summary>
        /// 左下markX 
        /// </summary>
        public double LeftDownMarkX = 0;
        /// <summary>
        /// 左下markY
        /// </summary>
        public double LeftDownMarkY = 0;

        /// <summary>
        /// 右下markX 
        /// </summary>
        public double RightDownMarkX = 0;
        /// <summary>
        /// 右下markY
        /// </summary>
        public double RightDownMarkY = 0;







        /// <summary>
        /// 检测是否完成
        /// </summary>
        public bool bTest = false;
        /// <summary>
        /// 尺寸检测结果是否合格
        /// </summary>
        public bool Ruselt = true;
        /// <summary>
        /// 极片头宽是否合格
        /// </summary>
        public bool bJPHeadWidth = true;
        /// <summary>
        /// 极片尾宽是否合格
        /// </summary>
        public bool bJPTailWidth = true;
        /// <summary>
        /// 极片头长是否合格
        /// </summary>
        public bool bJPHeadLength = true;
        /// <summary>
        /// 极片尾长是否合格
        /// </summary>
        public bool bJPTailLength = true;
        /// <summary>
        /// 极耳左肩宽是否合格
        /// </summary>
        public bool bJELeftShoulder = true;
        /// <summary>
        /// 极耳右肩宽是否合格
        /// </summary>
        public bool bJERightShoulder = true;
        /// <summary>
        /// 极耳宽是否合格
        /// </summary>
        public bool bJEWidth = true;
        /// <summary>
        /// 极耳高是否合格
        /// </summary>
        public bool bJEHeight = true;
        /// <summary>
        /// 负极带料高是否合格||正极陶瓷高
        /// </summary>
        public bool bDLHeightOrbCeramicsHeight = true;


        /// <summary>
        /// 左上相机V角度是否合格
        /// </summary>
        public bool bLeftUpVAngle = true;
        /// <summary>
        /// 左上相机V宽度是否合格
        /// </summary>
        public bool bLeftUpVWidth = true;
        /// <summary>
        /// 左上相机V深度是否合格
        /// </summary>
        public bool bLeftUpVDepth = true;
        /// <summary>
        /// 右上相机V角度是否合格
        /// </summary>
        public bool bRightUpVAngle = true;
        /// <summary>
        /// 右上相机V宽度是否合格
        /// </summary>
        public bool bRightUpVWidth = true;
        /// <summary>
        /// 右上相机V深度是否合格
        /// </summary>
        public bool bRightUpVDepth = true;
        /// <summary>
        /// 左下相机V角度是否合格
        /// </summary>
        public bool bLeftDownVAngle = true;
        /// <summary>
        /// 左下相机V宽度是否合格
        /// </summary>
        public bool bLeftDownVWidth = true;
        /// <summary>
        /// 左下相机V深度是否合格
        /// </summary>
        public bool bLeftDownVDepth = true;
        /// <summary>
        /// 右下相机V角度是否合格
        /// </summary>
        public bool bRightDownVAngle = true;
        /// <summary>
        /// 右下相机V宽度是否合格
        /// </summary>
        public bool bRightDownVWidth = true;
        /// <summary>
        /// 右下相机V深度是否合格
        /// </summary>
        public bool bRightDownVDepth = true;
        /// <summary>
        /// 极片总宽是否合格
        /// </summary>
        public bool bJPTotalWidth = true;
        /// <summary>
        /// 极片涂布高是否合格
        /// </summary>
        public bool bJPCoating = true;

        /// <summary>
        /// 对角线是否合格
        /// </summary>
        public bool bDiagonal = true;

        /// <summary>
        /// 左上相机角度是否合格
        /// </summary>
        public bool bLeftUpAngle = true;
        /// <summary>
        /// 右上相机角度是否合格
        /// </summary>
        public bool bRightUpAngle = true;

        /// <summary>
        /// 左下相机角度是否合格
        /// </summary>
        public bool bLeftDownAngle = true;
        /// <summary>
        /// 右下相机角度是否合格
        /// </summary>
        public bool bRightDownAngle = true;


        /// <summary>
        /// 极耳打折是否合格(2OK，3NG)
        /// </summary>
        public int JeBevelLimit = 2;
        /// <summary>
        /// 极耳打折是否合格
        /// </summary>
        public string bJeBevelLimit = "OK";
        /// <summary>
        /// 极耳余料是否合格
        /// </summary>
        public string bJeOddments = "OK";


        /// <summary>
        /// 左上缺角是否合格（true 合格，false 不合格）
        /// </summary>
        public bool bLeftUpBevel = true;

        /// <summary>
        /// 右上缺角是否合格（true 合格，false 不合格）
        /// </summary>
        public bool bRightUpBevel = true;


        /// <summary>
        /// 左下缺角是否合格（true 合格，false 不合格）
        /// </summary>
        public bool bLeftDownBevel = true;

        /// <summary>
        /// 右下缺角是否合格（true 合格，false 不合格）
        /// </summary>
        public bool bRightDownBevel = true;

        /// <summary>
        /// mark点是否合格(2=ok ,3=NG )
        /// </summary>
        public int Mark = 2;


        /// <summary>
        /// 班次
        /// </summary>
        public string WorkingShift = "白班";
        /// <summary>
        /// 极片类型（正负极）
        /// </summary>
        public string JPType;
        /// <summary>
        /// 不良类型
        /// </summary>
        public string NGType = "良品";

        /// <summary>
        /// 不良分类
        /// </summary>
        public string NGClassify = "";


        /// <summary>
        /// 是否为空片  false为空  true为有片
        /// </summary>
        public bool NullSlice = true;

        /// <summary>
        /// 检测耗时
        /// </summary>
        public string time = "0";


        #region

        /// <summary>
        /// 左上横边
        /// </summary>
        public bool LeftUpLateralEdge = true;
        /// <summary>
        /// 左上竖边
        /// </summary>
        public bool LeftUpVerticalEdge = true;
        /// <summary>
        /// 左上V横边
        /// </summary>
        public bool LeftUpVLateralEdge = true;
        /// <summary>
        /// 左上V斜边
        /// </summary>
        public bool LeftUpVBevelEdge = true;


        /// <summary>
        /// 右上横边
        /// </summary>
        public bool RightUpLateralEdge = true;
        /// <summary>
        /// 右上竖边
        /// </summary>
        public bool RightUpVerticalEdge = true;
        /// <summary>
        /// 右上V横边
        /// </summary>
        public bool RightUpVLateralEdge = true;
        /// <summary>
        /// 右上V斜边
        /// </summary>
        public bool RightUpVBevelEdge = true;


        /// <summary>
        /// 左下横边
        /// </summary>
        public bool LeftDownLateralEdge = true;
        /// <summary>
        /// 左下竖边
        /// </summary>
        public bool LeftDownVerticalEdge = true;
        /// <summary>
        /// 左下V横边
        /// </summary>
        public bool LeftDownVLateralEdge = true;
        /// <summary>
        /// 左下V斜边
        /// </summary>
        public bool LeftDownVBevelEdge = true;


        /// <summary>
        /// 右下横边
        /// </summary>
        public bool RightDownLateralEdge = true;
        /// <summary>
        /// 右下竖边
        /// </summary>
        public bool RightDownVerticalEdge = true;
        /// <summary>
        /// 右下V横边
        /// </summary>
        public bool RightDownVLateralEdge = true;
        /// <summary>
        /// 右下V斜边
        /// </summary>
        public bool RightDownVBevelEdge = true;


        /// <summary>
        /// 极耳横边
        /// </summary>
        public bool JELateralEdge = true;
        /// <summary>
        /// 极耳左竖边
        /// </summary>
        public bool JELeftVerticalEdge = true;
        /// <summary>
        ///极耳右竖边
        /// </summary>
        public bool JERightVerticalEdge = true;
        /// <summary>
        /// 陶瓷或者带料边
        /// </summary>
        public bool DLOrCeramicsEdge = true;

        #endregion 

        public Data() { }
    }


    /// <summary>
    /// 用户信息
    /// </summary>
    public struct UserInfo
    {
        public string name;
        public string password;
        public Power power;
    }

    /// <summary>
    /// 极片偏移数据与NG数
    /// </summary>
    public struct JPOffsetData
    {
        /// <summary>
        /// 极片偏移X最大值
        /// </summary>
        public double XMax;
        /// <summary>
        /// 极片偏移X最小值
        /// </summary>
        public double XMin;
        /// <summary>
        /// 极片偏移X标准差
        /// </summary>
        public double XSta;
        /// <summary>
        /// 极片偏移X平均值
        /// </summary>
        public double XAvg;
        /// <summary>
        /// 极片偏移Y最大值
        /// </summary>
        public double YMax;
        /// <summary>
        /// 极片偏移Y最小值
        /// </summary>
        public double YMin;
        /// <summary>
        /// 极片偏移Y标准差
        /// </summary>
        public double YSta;
        /// <summary>
        /// 极片偏移Y平均值
        /// </summary>
        public double YAvg;
        /// <summary>
        /// 极片偏移Z最大值
        /// </summary>
        public double ZMax;
        /// <summary>
        /// 极片偏移Z最大值
        /// </summary>
        public double ZMin;
        /// <summary>
        /// 极片偏移Z标准差
        /// </summary>
        public double ZSta;
        /// <summary>
        /// 极片偏移Z平均值
        /// </summary>
        public double ZAvg;
        /// <summary>
        /// 开始时间
        /// </summary>
        public DateTime StartTime;
        /// <summary>
        /// 结束时间
        /// </summary>
        public DateTime StopTime;

        public int Sum;
        public int SumNG;
        public int JPHeadLengthNG;
        public int JPTailLengthNG;
        public int JPHeadWidthNG;
        public int JPTailWidthNG;
        public int JEWidthNG;
        public int JEHeightNG;
        public int DLHeightOrCeramicsNG;
        public int JPTotalWidthNG;
        public int JPCoatingNG;
        public int DiagonalNG;
        public int MeasureLineNG;
        public int JEBevelLimitNG;
        public int JEOddmentsNG;
        public int JELeftShoulderNG;
        public int JERightShoulderNG;
        //垂直度
        public int LeftUpAngleNG;
        public int RightUpAngleNG;
        public int LeftDownAngleNG;
        public int RightDownAngleNG;
        //缺角
        public int LeftUpBevelNG;
        public int RightUpBevelNG;
        public int LeftDownBevelNG;
        public int RightDownBevelNG;

        //V角度
        public int LeftUpVAngleNG;
        public int RightUpVAngleNG;
        public int LeftDownVAngleNG;
        public int RightDownVAngleNG;
        //V宽度
        public int LeftUpVWidthNG;
        public int RightUpVWidthNG;
        public int LeftDownVWidthNG;
        public int RightDownVWidthNG;
        //V深度
        public int LeftUpVDepthNG;
        public int RightUpVDepthNG;
        public int LeftDownVDepthNG;
        public int RightDownVDepthNG;

        public int One;
        public int Two;
        public int Three;
    }




    public class User
    {
        public int ID;
        public string Name;//用户名
        public string Password;//密码
        public string RealName;//
        public string Rank;//级别

        public User(string user, string password, string realName, string rank)
        {
            Name = user;
            Password = password;
            RealName = realName;
            Rank = rank;
        }
        public User()
        {

        }
    }

    [StructLayout(LayoutKind.Sequential)]
    public struct SYSTEMTIME
    {
        public ushort wYear;
        public ushort wMonth;
        public ushort wDayOfWeek;
        public ushort wDay;
        public ushort wHour;
        public ushort wMinute;
        public ushort wSecond;
        public ushort wMilliseconds;

        public void FromDateTime(DateTime dateTime)
        {
            wYear = (ushort)dateTime.Year;
            wMonth = (ushort)dateTime.Month;
            wDayOfWeek = (ushort)dateTime.DayOfWeek;
            wDay = (ushort)dateTime.Day;
            wHour = (ushort)dateTime.Hour;
            wMinute = (ushort)dateTime.Minute;
            wSecond = (ushort)dateTime.Second;
            wMilliseconds = (ushort)dateTime.Millisecond;
        }

        public DateTime ToDateTime()
        {
            return new DateTime(wYear, wMonth, wDay, wHour, wMinute, wSecond);
        }
    }

    class Win32
    {
        [DllImport("Kernel32.dll")]
        public static extern bool SetSystemTime(ref SYSTEMTIME time);
        [DllImport("Kernel32.dll")]
        public static extern bool SetLocalTime(ref SYSTEMTIME time);
        [DllImport("Kernel32.dll")]
        public static extern bool GetSystemTime(ref SYSTEMTIME time);
        [DllImport("Kernel32.dll")]
        public static extern bool GetLocalTime(ref SYSTEMTIME time);
    }

    public class MouseChecker
    {
        [DllImport("user32.dll")]
        private static extern bool GetLastInputInfo(ref LASTINPUTINFO plii);

        [DllImport("kernel32.dll")]
        private static extern uint GetLastError();

        [StructLayout(LayoutKind.Sequential)]
        private struct LASTINPUTINFO
        {
            public uint cbSize;
            public uint dwTime;
        }

        public static uint GetIdleTime()
        {
            LASTINPUTINFO lastInputInfo = new LASTINPUTINFO();
            lastInputInfo.cbSize = (uint)Marshal.SizeOf(lastInputInfo);
            if (!GetLastInputInfo(ref lastInputInfo))
            {
                throw new Exception($"Failed to get last input info. Error: {GetLastError()}");
            }
            return (uint)Environment.TickCount - lastInputInfo.dwTime;
        }
        /// <summary>
        /// 判断是否有人操作鼠标
        /// </summary>
        /// <returns></returns>
        public static bool IsMouseActive()
        {
            uint idleTime = GetIdleTime();
            const uint ACTIVE_MOUSE_TIME = 3000; // 3 seconds
            return idleTime < ACTIVE_MOUSE_TIME;
        }
    }


    #region 电脑性能监控类
    public class Funtion
    {
        private static SysParams sysParams;//性能计数器管理类
        static Funtion()
        {
            sysParams = new SysParams();
        }



        /// <summary>
        /// 磁盘空间大小监视报警
        /// </summary>
        /// <param name="alarmValue">报警值</param>
        /// <param name="drive">盘符</param>     
        /// <returns>报警</returns>
        public static bool DiskMonitoring(double alarmValue, string drive)
        {
            double all = GetHardDiskSpace(drive);//总大小
            double residue = GetHardDiskFreeSpace(drive);//剩余空间
            double percent = Convert.ToDouble((all - residue)) / Convert.ToDouble(all);
            if (Math.Round(percent, 2) * 100 > alarmValue)
            {
                return true;//报警
            }
            else
            {
                return false;
            }
        }
        /// <summary>
        /// 磁盘读写所占时间百分比
        /// </summary>
        /// <param name="alarmValue">报警值</param>
        /// <param name="drive">盘符</param>     
        /// <returns>报警</returns>
        public static double DiskTimeMonitoring(/*double alarmValue*/)
        {
            sysParams.getDiskTime();//时间百分比
            return Math.Round(sysParams.DISKTime, 2);
            //if (sysParams.DISKTime > alarmValue)
            //{
            //    return true;//报警
            //}
            //else
            //{
            //    return false;
            //}
        }
        /// <summary>
        /// 磁盘读取速度
        /// </summary>
        public static double DiskReadMonitoring()
        {
            sysParams.getDiskRead();//读取速度
            return sysParams.DISKRead;


        }
        /// <summary>
        /// 磁盘写入速度
        /// </summary>     
        public static double DiskWriteMonitoring()
        {
            sysParams.getDiskWrite();//读取速度
            return sysParams.DISKWrite;


        }
        /// <summary> 
        /// 电脑内存大小监视报警
        /// </summary>      
        public static double MemoryMonitoring()
        {
            sysParams.getMemAvailable();//当前已使用内存
            double usableMemory = sysParams.MEMAvailable;
            double allMemory = GetPhisicalMemory();//总内存
            double percent = Convert.ToDouble((allMemory - usableMemory)) / Convert.ToDouble(allMemory);
            return Math.Round(percent, 2) * 100;

        }
        /// <summary> 
        /// 软件内存大小监视报警
        /// </summary>
        public static double SoftwareMemoryMonitoring()
        {
            double allMemory = GetPhisicalMemory();//总内存
            double usedMemory = 0;
            Process p = Process.GetCurrentProcess();
            if (p != null)
            {
                p.Refresh();
                string procName = p.ProcessName;
                using (PerformanceCounter pc = new PerformanceCounter("Process", "Working Set - Private", procName))
                {
                    usedMemory = (pc.NextValue() / 1024.0 / 1024.0);
                }

            }
            //double percent = Convert.ToDouble(usedMemory) / Convert.ToDouble(allMemory);
            return Math.Round(usedMemory / allMemory, 2) * 100;
            //if (Math.Round(percent, 2) * 100 > alarmValue)
            //{
            //    return true;//报警
            //}
            //else
            //{
            //    return false;
            //}
        }

        /// <summary>
        /// 获取指定驱动器的空间总大小(单位为B)
        /// </summary>
        /// <param name="只需输入代表驱动器的字母即可（大写）"></param>
        /// <returns></returns>
        private static long GetHardDiskSpace(string str_HardDiskName)
        {
            long totalSize = new long();
            str_HardDiskName = str_HardDiskName + ":\\";
            System.IO.DriveInfo[] drives = System.IO.DriveInfo.GetDrives();
            foreach (System.IO.DriveInfo drive in drives)
            {
                if (drive.Name == str_HardDiskName)
                {
                    totalSize = drive.TotalSize / (1024 * 1024);
                }
            }
            return totalSize;
        }
        /// <summary>
        /// 获取指定驱动器的剩余空间总大小(单位为B)
        /// </summary>
        /// <param name="只需输入代表驱动器的字母即可（大写）"></param>
        /// <returns></returns>
        private static long GetHardDiskFreeSpace(string str_HardDiskName)
        {
            long freeSpace = new long();
            str_HardDiskName = str_HardDiskName + ":\\";
            System.IO.DriveInfo[] drives = System.IO.DriveInfo.GetDrives();
            foreach (System.IO.DriveInfo drive in drives)
            {
                if (drive.Name == str_HardDiskName)
                {
                    freeSpace = drive.TotalFreeSpace / (1024 * 1024);
                }
            }
            return freeSpace;
        }


        /// <summary>
        /// 获取系统内存大小
        /// </summary>
        /// <returns>内存大小（单位M）</returns>
        private static double GetPhisicalMemory()
        {
            ManagementObjectSearcher searcher = new ManagementObjectSearcher();   //用于查询一些如系统信息的管理对象 
            searcher.Query = new SelectQuery(WindowsAPIType.Win32_PhysicalMemory.ToString(), "",
            new string[] { WindowsAPIKeys.Capacity.ToString() });//设置查询条件 
            ManagementObjectCollection collection = searcher.Get();   //获取内存容量 
            ManagementObjectCollection.ManagementObjectEnumerator em = collection.GetEnumerator();

            long capacity = 0;
            while (em.MoveNext())
            {
                ManagementBaseObject baseObj = em.Current;
                if (baseObj.Properties[WindowsAPIKeys.Capacity.ToString()].Value != null)
                {
                    try
                    {
                        capacity += long.Parse(baseObj.Properties[WindowsAPIKeys.Capacity.ToString()].Value.ToString());
                    }
                    catch
                    {
                        return -1;
                    }
                }
            }
            return GetMB(capacity);
        }
        /// <summary>
        /// 将B转换为MB
        /// </summary>
        /// <param name="b"></param>
        /// <returns></returns>
        private static double GetMB(long b)
        {
            for (int i = 0; i < 2; i++)
            {
                b /= 1024;
            }
            return b;
        }
    }

    public class SysParams

    {
        public string NodeName { get; set; }

        public float CPUProcessorTime { get; set; }

        public float CPUPrivilegedTime { get; set; }

        public float CPUInterruptTime { get; set; }

        public float CPUDPCTime { get; set; }

        public float MEMAvailable { get; set; }

        public float MEMCommited { get; set; }

        public float MEMCommitLimit { get; set; }

        public float MEMCommitedPerc { get; set; }

        public float MEMPoolPaged { get; set; }

        public float MEMPoolNonPaged { get; set; }

        public float MEMCached { get; set; }

        public float PageFile { get; set; }

        public float ProcessorQueueLengh { get; set; }

        public float DISCQueueLengh { get; set; }

        public float DISKRead { get; set; }

        public float DISKWrite { get; set; }

        public float DISKAverageTimeRead { get; set; }

        public float DISKAverageTimeWrite { get; set; }

        public float DISKTime { get; set; }

        public float HANDLECountCounter { get; set; }

        public float THREADCount { get; set; }

        public int CONTENTSwitches { get; set; }

        public int SYSTEMCalls { get; set; }

        public float NetTrafficSend { get; set; }

        public float NetTrafficReceive { get; set; }

        public DateTime SamplingTime { get; set; }

        private PerformanceCounter cpuProcessorTime = new PerformanceCounter("Processor", "% Processor Time", "_Total");

        private PerformanceCounter cpuPrivilegedTime = new PerformanceCounter("Processor", "% Privileged Time", "_Total");

        private PerformanceCounter cpuInterruptTime = new PerformanceCounter("Processor", "% Interrupt Time", "_Total");

        private PerformanceCounter cpuDPCTime = new PerformanceCounter("Processor", "% DPC Time", "_Total");

        private PerformanceCounter memAvailable = new PerformanceCounter("Memory", "Available MBytes", null);

        private PerformanceCounter memCommited = new PerformanceCounter("Memory", "Committed Bytes", null);

        private PerformanceCounter memCommitLimit = new PerformanceCounter("Memory", "Commit Limit", null);

        private PerformanceCounter memCommitedPerc = new PerformanceCounter("Memory", "% Committed Bytes In Use", null);

        private PerformanceCounter memPollPaged = new PerformanceCounter("Memory", "Pool Paged Bytes", null);

        private PerformanceCounter memPollNonPaged = new PerformanceCounter("Memory", "Pool Nonpaged Bytes", null);

        private PerformanceCounter memCached = new PerformanceCounter("Memory", "Cache Bytes", null);

        private PerformanceCounter pageFile = new PerformanceCounter("Paging File", "% Usage", "_Total");

        private PerformanceCounter processorQueueLengh = new PerformanceCounter("System", "Processor Queue Length", null);

        private PerformanceCounter diskQueueLengh = new PerformanceCounter("PhysicalDisk", "Avg. Disk Queue Length", "_Total");

        private PerformanceCounter diskRead = new PerformanceCounter("PhysicalDisk", "Disk Read Bytes/sec", "_Total");

        private PerformanceCounter diskWrite = new PerformanceCounter("PhysicalDisk", "Disk Write Bytes/sec", "_Total");

        private PerformanceCounter diskAverageTimeRead = new PerformanceCounter("PhysicalDisk", "Avg. Disk sec/Read", "_Total");

        private PerformanceCounter diskAverageTimeWrite = new PerformanceCounter("PhysicalDisk", "Avg. Disk sec/Write", "_Total");

        private PerformanceCounter diskTime = new PerformanceCounter("PhysicalDisk", "% Disk Time", "_Total");

        private PerformanceCounter handleCountCounter = new PerformanceCounter("Process", "Handle Count", "_Total");

        private PerformanceCounter threadCount = new PerformanceCounter("Process", "Thread Count", "_Total");

        private PerformanceCounter contentSwitches = new PerformanceCounter("System", "Context Switches/sec", null);

        private PerformanceCounter systemCalls = new PerformanceCounter("System", "System Calls/sec", null);

        private PerformanceCounterCategory performanceNetCounterCategory;

        private PerformanceCounter[] trafficSentCounters;

        private PerformanceCounter[] trafficReceivedCounters;

        private string[] interfaces = null;

        public void initNetCounters()

        {

            // PerformanceCounter(CategoryName,CounterName,InstanceName)

            performanceNetCounterCategory = new PerformanceCounterCategory("Network Interface");

            interfaces = performanceNetCounterCategory.GetInstanceNames();

            int length = interfaces.Length;

            if (length > 0)

            {

                trafficSentCounters = new PerformanceCounter[length];

                trafficReceivedCounters = new PerformanceCounter[length];

            }

            for (int i = 0; i < length; i++)

            {

                // Initializes a new, read-only instance of the PerformanceCounter class.

                //   1st paramenter: "categoryName"-The name of the performance counter category (performance object) with which this performance counter is associated.

                //   2nd paramenter: "CounterName" -The name of the performance counter.

                //   3rd paramenter: "instanceName" -The name of the performance counter category instance, or an empty string (""), if the category contains a single instance.

                trafficReceivedCounters[i] = new PerformanceCounter("Network Interface", "Bytes Sent/sec", interfaces[i]);

                trafficSentCounters[i] = new PerformanceCounter("Network Interface", "Bytes Sent/sec", interfaces[i]);

            }

            // List of all names of the network interfaces

            for (int i = 0; i < length; i++)

            {

                Console.WriteLine("Name netInterface: {0}", performanceNetCounterCategory.GetInstanceNames()[i]);

            }

        }

        public void getProcessorCpuTime()
        {

            float tmp = cpuProcessorTime.NextValue();

            CPUProcessorTime = (float)(Math.Round((double)tmp, 1));

            // Environment.ProcessorCount: return the total number of cores

        }

        public void getCpuPrivilegedTime()

        {

            float tmp = cpuPrivilegedTime.NextValue();

            CPUPrivilegedTime = (float)(Math.Round((double)tmp, 1));

        }

        public void getCpuinterruptTime()

        {

            float tmp = cpuInterruptTime.NextValue();

            CPUInterruptTime = (float)(Math.Round((double)tmp, 1));

        }

        public void getcpuDPCTime()

        {

            float tmp = cpuDPCTime.NextValue();

            CPUDPCTime = (float)(Math.Round((double)tmp, 1));

        }

        public void getPageFile()

        {

            PageFile = pageFile.NextValue();

        }

        public void getProcessorQueueLengh()

        {

            ProcessorQueueLengh = processorQueueLengh.NextValue();

        }

        public void getMemAvailable()

        {

            MEMAvailable = memAvailable.NextValue();

        }

        public void getMemCommited()

        {

            MEMCommited = memCommited.NextValue() / (1024 * 1024);

        }

        public void getMemCommitLimit()

        {

            MEMCommitLimit = memCommitLimit.NextValue() / (1024 * 1024);

        }

        public void getMemCommitedPerc()

        {

            float tmp = memCommitedPerc.NextValue();

            // return the value of Memory Commit Limit

            MEMCommitedPerc = (float)(Math.Round((double)tmp, 1));

        }

        public void getMemPoolPaged()

        {

            float tmp = memPollPaged.NextValue() / (1024 * 1024);

            MEMPoolPaged = (float)(Math.Round((double)tmp, 1));

        }

        public void getMemPoolNonPaged()

        {

            float tmp = memPollNonPaged.NextValue() / (1024 * 1024);

            MEMPoolNonPaged = (float)(Math.Round((double)tmp, 1));

        }

        public void getMemCachedBytes()

        {

            // return the value of Memory Cached in MBytes

            MEMCached = memCached.NextValue() / (1024 * 1024);

        }

        public void getDiskQueueLengh()

        {

            DISCQueueLengh = diskQueueLengh.NextValue();

        }

        public void getDiskRead()

        {

            float tmp = diskRead.NextValue() / 1024;

            DISKRead = (float)(Math.Round((double)tmp, 1));

        }

        public void getDiskWrite()

        {

            float tmp = diskWrite.NextValue() / 1024;

            DISKWrite = (float)(Math.Round((double)tmp, 1)); // round 1 digit decimal

        }

        public void getDiskAverageTimeRead()

        {

            float tmp = diskAverageTimeRead.NextValue() * 1000;

            DISKAverageTimeRead = (float)(Math.Round((double)tmp, 1)); // round 1 digit decimal

        }

        public void getDiskAverageTimeWrite()

        {

            float tmp = diskAverageTimeWrite.NextValue() * 1000;

            DISKAverageTimeWrite = (float)(Math.Round((double)tmp, 1)); // round 1 digit decimal

        }

        public void getDiskTime()

        {

            float tmp = diskTime.NextValue();

            DISKTime = (float)(Math.Round((double)tmp, 1));

        }



        public void getHandleCountCounter()

        {

            HANDLECountCounter = handleCountCounter.NextValue();

        }

        public void getThreadCount()

        {

            THREADCount = threadCount.NextValue();

        }

        public void getContentSwitches()

        {

            CONTENTSwitches = (int)Math.Ceiling(contentSwitches.NextValue());

        }

        public void getsystemCalls()

        {

            SYSTEMCalls = (int)Math.Ceiling(systemCalls.NextValue());

        }

        public void getCurretTrafficSent()

        {

            int length = interfaces.Length;

            float sendSum = 0.0F;

            for (int i = 0; i < length; i++)

            {

                sendSum += trafficSentCounters[i].NextValue();

            }

            float tmp = 8 * (sendSum / 1024);

            NetTrafficSend = (float)(Math.Round((double)tmp, 1));

        }

        public void getCurretTrafficReceived()

        {

            int length = interfaces.Length;

            float receiveSum = 0.0F;

            for (int i = 0; i < length; i++)

            {

                receiveSum += trafficReceivedCounters[i].NextValue();

            }

            float tmp = 8 * (receiveSum / 1024);

            NetTrafficReceive = (float)(Math.Round((double)tmp, 1));

        }

        public void getSampleTime()

        {

            SamplingTime = DateTime.Now;

        }

    }

    public enum WindowsAPIType
    {
        /// <summary>
        /// 内存
        /// </summary>
        Win32_PhysicalMemory,
        /// <summary>
        /// cpu
        /// </summary>
        Win32_Processor,
        /// <summary>
        /// 硬盘
        /// </summary>
        win32_DiskDrive,
        /// <summary>
        /// 电脑型号
        /// </summary>
        Win32_ComputerSystemProduct,
        /// <summary>
        /// 分辨率
        /// </summary>
        Win32_DesktopMonitor,
        /// <summary>
        /// 显卡
        /// </summary>
        Win32_VideoController,
        /// <summary>
        /// 操作系统
        /// </summary>
        Win32_OperatingSystem

    }
    public enum WindowsAPIKeys
    {
        /// <summary>
        /// 名称
        /// </summary>
        Name,
        /// <summary>
        /// 显卡芯片
        /// </summary>
        VideoProcessor,
        /// <summary>
        /// 显存大小
        /// </summary>
        AdapterRAM,
        /// <summary>
        /// 分辨率宽
        /// </summary>
        ScreenWidth,
        /// <summary>
        /// 分辨率高
        /// </summary>
        ScreenHeight,
        /// <summary>
        /// 电脑型号
        /// </summary>
        Version,
        /// <summary>
        /// 硬盘容量
        /// </summary>
        Size,
        /// <summary>
        /// 内存容量
        /// </summary>
        Capacity,
        /// <summary>
        /// cpu核心数
        /// </summary>
        NumberOfCores
    }
    #endregion

    public class ToastNotification : Form
    {
        #region MyRegion
        //// 定时器：控制渐显、自动关闭、渐隐
        //private readonly Timer _fadeInTimer = new Timer { Interval = 50 };
        //private readonly Timer _autoCloseTimer = new Timer();
        //private readonly Timer _fadeOutTimer = new Timer { Interval = 50 };
        //private int _autoCloseSeconds = 3;

        //// 线程安全调用的委托
        //private delegate void ShowToastDelegate(string message, int autoCloseSeconds);

        //// 构造函数
        //private ToastNotification(string message, int autoCloseSeconds)
        //{
        //    _autoCloseSeconds = autoCloseSeconds;
        //    InitializeUI(message);
        //    InitializeTimers();
        //    SetPositionToBottomRight();
        //}

        //// 初始化UI
        //private void InitializeUI(string message)
        //{
        //    // 窗体基本设置
        //    Text = "提示";
        //    Size = new Size(300, 120);
        //    FormBorderStyle = FormBorderStyle.FixedSingle;
        //    MaximizeBox = false;
        //    MinimizeBox = false;
        //    ShowInTaskbar = false;
        //    TopMost = true;
        //    Opacity = 0;  // 初始透明（用于渐显）
        //    BackColor = Color.LightSkyBlue;

        //    // 提示文本标签
        //    var lblMessage = new Label
        //    {
        //        Text = message,
        //        Dock = DockStyle.Fill,
        //        TextAlign = ContentAlignment.MiddleCenter,
        //        Padding = new Padding(10),
        //        Font = new Font("宋体", 9F, FontStyle.Regular),  // 确保系统兼容字体
        //        AutoSize = false,
        //        ForeColor = Color.DarkBlue
        //    };
        //    Controls.Add(lblMessage);

        //    //// 关闭按钮
        //    //var btnClose = new System.Windows.Forms.Button
        //    //{
        //    //    Text = "关闭",
        //    //    Dock = DockStyle.Bottom,
        //    //    Height = 30,
        //    //    FlatStyle = FlatStyle.Flat,
        //    //    BackColor = Color.LightGray
        //    //};
        //    //btnClose.Click += (s, e) => StartFadeOut();
        //    //Controls.Add(btnClose);
        //}

        //// 初始化定时器逻辑
        //private void InitializeTimers()
        //{
        //    // 渐显逻辑
        //    _fadeInTimer.Tick += (s, e) =>
        //    {
        //        if (Opacity < 1.0)
        //            Opacity += 0.1;
        //        else
        //            _fadeInTimer.Stop();
        //    };

        //    // 自动关闭逻辑
        //    _autoCloseTimer.Interval = _autoCloseSeconds * 1000;
        //    _autoCloseTimer.Tick += (s, e) =>
        //    {
        //        _autoCloseTimer.Stop();
        //        StartFadeOut();
        //    };

        //    // 渐隐逻辑
        //    _fadeOutTimer.Tick += (s, e) =>
        //    {
        //        if (Opacity > 0)
        //            Opacity -= 0.1;
        //        else
        //        {
        //            _fadeOutTimer.Stop();
        //            Close();
        //        }
        //    };
        //}

        ////// 设置到右下角
        ////private void SetPositionToBottomRight()
        ////{
        ////    Screen screen = Screen.PrimaryScreen;
        ////    Rectangle workingArea = screen.WorkingArea;
        ////    // 计算位置（右下角，带边距）
        ////    int x = workingArea.Right - Width - 15;
        ////    int y = workingArea.Bottom - Height - 15;
        ////    Location = new Point(x, y);
        ////}

        //private void SetPositionToBottomRight()
        //{
        //    // 获取当前窗体所在的屏幕（支持多显示器）
        //    Screen currentScreen = Screen.FromControl(this);
        //    // 获取屏幕工作区（排除任务栏，无论任务栏在哪个位置）
        //    Rectangle workingArea = currentScreen.WorkingArea;

        //    // 计算右下角坐标（向右和向下各偏移15px，避免贴边）
        //    int x = workingArea.Right - this.Width - 15;
        //    int y = workingArea.Bottom - this.Height - 15;

        //    // 确保坐标不会超出屏幕范围（极端情况处理）
        //    x = Math.Max(workingArea.Left, x);
        //    y = Math.Max(workingArea.Top, y);

        //    this.Location = new Point(x, y);
        //}


        //// 开始渐隐关闭
        //private void StartFadeOut()
        //{
        //    _fadeInTimer.Stop();
        //    _autoCloseTimer.Stop();
        //    _fadeOutTimer.Start();
        //}

        //// 线程安全的静态显示方法（核心入口）
        //public static void Show(string message, int autoCloseSeconds = 3)
        //{
        //    // 获取应用程序主窗体（UI线程载体）
        //    Form mainForm = null;
        //    try
        //    {
        //        // 在UI线程中获取主窗体
        //        if (Application.OpenForms.Count > 0)
        //        {
        //            mainForm = Application.OpenForms[0];
        //        }
        //    }
        //    catch { /* 忽略获取主窗体失败的情况 */ }

        //    // 如果没有主窗体，直接在当前线程显示（可能非UI线程，做兼容处理）
        //    if (mainForm == null || mainForm.IsDisposed)
        //    {
        //        var toast = new ToastNotification(message, autoCloseSeconds);
        //        toast.Show();
        //        toast._fadeInTimer.Start();
        //        toast._autoCloseTimer.Start();
        //        return;
        //    }

        //    // 检查是否需要跨线程调用
        //    if (mainForm.InvokeRequired)
        //    {
        //        // 非UI线程：通过委托切换到UI线程
        //        mainForm.Invoke(new ShowToastDelegate(Show), message, autoCloseSeconds);
        //    }
        //    else
        //    {
        //        // UI线程：直接显示
        //        var toast = new ToastNotification(message, autoCloseSeconds);
        //        toast.Show();
        //        toast._fadeInTimer.Start();
        //        toast._autoCloseTimer.Start();
        //    }
        //}

        //// 释放资源
        //protected override void Dispose(bool disposing)
        //{
        //    if (disposing)
        //    {
        //        _fadeInTimer.Dispose();
        //        _autoCloseTimer.Dispose();
        //        _fadeOutTimer.Dispose();
        //    }
        //    base.Dispose(disposing);
        //}
        #endregion

        // 静态列表：跟踪所有显示中的提示框（用于计算堆叠位置）
        private static readonly List<ToastNotification> _activeToasts = new List<ToastNotification>();
        // 线程安全锁
        private static readonly object _lockObj = new object();

        // 定时器
        private readonly Timer _fadeInTimer = new Timer { Interval = 50 };
        private readonly Timer _autoCloseTimer = new Timer();
        private readonly Timer _fadeOutTimer = new Timer { Interval = 50 };
        private int _autoCloseSeconds = 3;
        // 弹窗之间的间距
        private const int _spacing = 5;

        // 线程安全委托
        private delegate void ShowToastDelegate(string message, int autoCloseSeconds);

        private ToastNotification(string message, int autoCloseSeconds)
        {
            _autoCloseSeconds = autoCloseSeconds;
            InitializeUI(message);
            InitializeTimers();
            SetPositionToStackedBottomRight(); // 堆叠定位
            RegisterForPositionUpdates(); // 注册位置更新事件
        }

        private void InitializeUI(string message)
        {
            Text = "提示";
            Size = new Size(300, 120);
            FormBorderStyle = FormBorderStyle.FixedSingle;
            MaximizeBox = false;
            MinimizeBox = false;
            ShowInTaskbar = false;
            TopMost = true;
            Opacity = 0;
            BackColor = Color.LightSkyBlue;
            ForeColor = Color.DarkBlue;

            // 提示文本
            var lblMessage = new Label
            {
                Text = message,
                Dock = DockStyle.Fill,
                TextAlign = ContentAlignment.MiddleCenter,
                Padding = new Padding(10),
                Font = new Font("宋体", 9F),
                AutoSize = false
            };
            Controls.Add(lblMessage);

            //// 关闭按钮
            //var btnClose = new Button
            //{
            //    Text = "关闭",
            //    Dock = DockStyle.Bottom,
            //    Height = 30,
            //    FlatStyle = FlatStyle.Flat,
            //    BackColor = Color.LightGray
            //};
            //btnClose.Click += (s, e) => StartFadeOut();
            //Controls.Add(btnClose);
        }

        private void InitializeTimers()
        {
            // 渐显
            _fadeInTimer.Tick += (s, e) =>
            {
                if (Opacity < 1.0)
                    Opacity += 0.1;
                else
                    _fadeInTimer.Stop();
            };

            // 自动关闭
            _autoCloseTimer.Interval = _autoCloseSeconds * 1000;
            _autoCloseTimer.Tick += (s, e) =>
            {
                _autoCloseTimer.Stop();
                StartFadeOut();
            };

            // 渐隐
            _fadeOutTimer.Tick += (s, e) =>
            {
                if (Opacity > 0)
                    Opacity -= 0.1;
                else
                {
                    _fadeOutTimer.Stop();
                    Close();
                }
            };
        }

        // 核心：计算堆叠位置（新弹窗在前一个弹窗上方）
        private void SetPositionToStackedBottomRight()
        {
            lock (_lockObj)
            {
                // 获取当前屏幕工作区
                Screen currentScreen = Screen.FromControl(this);
                Rectangle workingArea = currentScreen.WorkingArea;

                // 基础X坐标（右下角水平位置）
                int x = workingArea.Right - Width - 5;

                // 计算Y坐标：基础位置 - 所有已显示弹窗的总高度（含间距）
                int y = workingArea.Bottom - Height - 15;
                foreach (var toast in _activeToasts)
                {
                    if (!toast.IsDisposed)
                        y -= (toast.Height + _spacing);
                }

                // 确保不超出屏幕上边界
                y = Math.Max(workingArea.Top + 10, y);

                Location = new Point(x, y);
            }
        }

        // 注册事件：当有弹窗关闭时，更新其他弹窗位置
        private void RegisterForPositionUpdates()
        {
            // 当当前弹窗关闭时，从列表移除并通知其他弹窗更新位置
            FormClosed += (s, e) =>
            {
                lock (_lockObj)
                {
                    _activeToasts.Remove(this);
                }
                UpdateAllToastPositions();
            };

            // 将当前弹窗加入活跃列表
            lock (_lockObj)
            {
                _activeToasts.Add(this);
            }
        }

        // 当有弹窗关闭时，更新所有剩余弹窗的位置
        private void UpdateAllToastPositions()
        {
            // 确保在UI线程执行
            if (InvokeRequired)
            {
                Invoke(new Action(UpdateAllToastPositions));
                return;
            }

            lock (_lockObj)
            {
                // 按显示顺序重新排列所有弹窗
                foreach (var toast in _activeToasts)
                {
                    if (!toast.IsDisposed)
                        toast.SetPositionToStackedBottomRight();
                }
            }
        }

        private void StartFadeOut()
        {
            _fadeInTimer.Stop();
            _autoCloseTimer.Stop();
            _fadeOutTimer.Start();
        }

        // 线程安全的显示方法
        public static void Show(string message, int autoCloseSeconds = 4)
        {
            Form mainForm = null;
            try
            {
                if (System.Windows.Forms.Application.OpenForms.Count > 0)
                    mainForm = System.Windows.Forms.Application.OpenForms[0];
            }
            catch { }

            if (mainForm == null || mainForm.IsDisposed)
            {
                var toast = new ToastNotification(message, autoCloseSeconds);
                toast.Show();
                toast._fadeInTimer.Start();
                toast._autoCloseTimer.Start();
                return;
            }

            if (mainForm.InvokeRequired)
            {
                mainForm.Invoke(new ShowToastDelegate(Show), message, autoCloseSeconds);
            }
            else
            {
                var toast = new ToastNotification(message, autoCloseSeconds);
                toast.Show();
                toast._fadeInTimer.Start();
                toast._autoCloseTimer.Start();
            }
        }

        protected override void Dispose(bool disposing)
        {
            if (disposing)
            {
                _fadeInTimer.Dispose();
                _autoCloseTimer.Dispose();
                _fadeOutTimer.Dispose();
            }
            base.Dispose(disposing);
        }
    }

}
